Step 34: Validate ObjectID
We should be validating the input to Bookmark DAO operations. Namely, we should validate the ID parameter.
Add the following imports at the top of src/data/BookmarkDAO.js
file:
import { z } from "zod";
import mongoose from "mongoose";
Update the following operation in the same file
// return the bookmark with the given id
// return null if resource does not exist in our database
// throws ApiError if id is invalid
async read(id) {
try {
z.string()
.refine((id) => mongoose.isValidObjectId(id), {
message: "Invalid ID!",
})
.parse(id);
const bookmark = await Bookmark.findById(id);
return bookmark;
} catch (err) {
throw new ApiError(400, err.message);
}
}
Update the following tests in the tests/data/BookmarkDAO.test.js
file”
it("test read() given invalid ID", async () => {
try {
await bookmarkDAO.read("invalid");
} catch (err) {
expect(err.status).toBe(400);
}
});
it("test read() given valid but non-existing ID", async () => {
const _bookmark = await bookmarkDAO.read(
mongoose.Types.ObjectId().toString()
);
expect(_bookmark).toBeNull();
});
Let’s update the BookmarkDAO.js
to validate object IDs for other operations too. First, refactor the code by adding the following helper function before the class declaration.
const validObjectId = z.string().refine((id) => mongoose.isValidObjectId(id), {
message: "Invalid ID!",
});
Next, update the read
operation:
// return the bookmark with the given id
// return null if resource does not exist in our database
// throws ApiError if id is invalid
async read(id) {
try {
validObjectId.parse(id);
const bookmark = await Bookmark.findById(id);
return bookmark;
} catch (err) {
throw new ApiError(400, err.message);
}
}
Now update the delete
and update
operations and add tests for them!
Run all the tests and make sure they all pass. Then, save and commit changes.